import numpy as np
import pandas as pd
# from autoviz.AutoViz_Class import AutoViz_Class
import plotly.express as px
from matplotlib import pyplot as plt
import seaborn as sns
# 读取csv文件，以制表符分隔
df = pd.read_csv('marketing_campaign.csv', sep="\t")
# 删除缺失值
df.dropna(inplace=True)
# 将年份出生转换为年龄
df["Year_Birth"] = 2023 - df["Year_Birth"]
# 计算消费总和
df["Spent"] = df["MntWines"] + df["MntFruits"] + df["MntMeatProducts"] + df["MntFishProducts"] + df[
    "MntSweetProducts"] + df["MntGoldProds"]
# 重命名年龄列
# df = pd.get_dummies(df)
df.rename(columns = {'Year_Birth':'Age'},inplace = True)
y = df.drop(['Education','Marital_Status','Dt_Customer'],axis = 1)
# 绘制热力图
plt.figure(figsize=(16,9))
ax = sns.heatmap(df.corr(),annot = True,cmap = 'viridis')
plt.savefig('heatmap.png')
plt.show()


# 定义一个函数corrMat，用于绘制相关矩阵
def corrMat(df, id=False):
    # 计算相关矩阵
    corr_mat = df.corr().round(2)
    # 创建一个图形
    f, ax = plt.subplots(figsize=(12, 7))
    # 创建一个上三角矩阵，用于掩码
    mask = np.triu(np.ones_like(corr_mat, dtype=bool))
    # 掩码，从第一行开始，到倒数第二行结束
    mask = mask[1:, :-1]
    # 拷贝相关矩阵，从第一行开始，到倒数第二行结束
    corr = corr_mat.iloc[1:, :-1].copy()
    # 绘制热力图
    sns.heatmap(corr, mask=mask, vmin=-0.3, vmax=0.3, center=0,
                cmap='RdPu_r', square=False, lw=2, annot=True, cbar=False)
    # 获取y轴的起始和结束位置
    bottom, top = ax.get_ylim()
    # 设置y轴的起始和结束位置
    ax.set_ylim(bottom + 0.5, top - 0.5)
    # 设置标题
    ax.set_title('Shifted Linear Correlation Matrix')
    # 显示图形
    plt.show()

# 调用corrMat函数
corrMat(df)
sns.pairplot(df[['Income','Age','Recency','Spent','Marital_Status']])
plt.savefig('pairplot.png')
plt.show()

# 检查用户是否具有不同教育水平
df['Education'].value_counts()
# 绘制教育水平频率图
sns.countplot(x = 'Education' , data = df)
plt.show()
# 检查用户是否具有不同婚姻状态
df['Marital_Status'].value_counts()
# 绘制婚姻状态频率图
sns.countplot( x = 'Marital_Status',data = df)
plt.savefig('marital_status.png')
plt.show()

# 检查用户是否具有不同教育水平
obj = ['Education','Marital_Status']
# 遍历检查用户是否具有不同教育水平
for i in obj:
    # 复制数据
    data=df.copy()
    # 绘制年龄平均值图表
    data.groupby(i)['Age'].mean().plot.bar()
    # 设置x轴标签
    plt.xlabel(i)
    # 设置y轴标签
    plt.ylabel('Age')
    # 设置图表标题
    plt.title(i)
    plt.show()


# 遍历obj中的每一个元素
for i in range(len(obj)):
    # 遍历obj中的每一个元素中的每一个元素
    for j in range(2):
        # 获取obj中的每一个元素
        x = obj[i]
        # 如果obj中的每一个元素中的每一个元素不等于obj中的第一个元素
        if obj[j] != x:
            # 绘制柱状图
            sns.barplot(x= x,y='Age',hue=obj[j],data=df)
            # 设置图例的位置
            plt.legend(bbox_to_anchor=(1.1, 1.05))
            plt.show()
# 定义一个函数，用于绘制年龄和婚姻状态的图表
df7 = df.copy()
# 复制一份数据
for i in range(len(obj)):
    # 遍历obj中的每一个元素
    x='Marital_Status'
    # 将婚姻状态赋值给x
    for j in range(1):
        # 遍历1次
        if obj[i] != x:
            # 如果obj[i]不等于x
            sns.barplot(x= x,y='Age',hue=obj[i],data=df7)
            # 绘制年龄和婚姻状态的图表
            sns.set(rc={'figure.figsize':(11,12)})
            # 设置图表的大小
            plt.show()

# 遍历obj中的每一个元素
for i in range(len(obj)):
    # 将obj中的元素赋值给x
    x='Marital_Status'
    # 遍历obj中的每一个元素
    for j in range(1):
        # 如果obj中的元素不等于x
        if obj[i] != x:
            # 绘制条形图，x轴为x，y轴为Income，hue为obj中的元素，数据为df7
            sns.barplot(x= x,y='Income',hue=obj[i],data=df7)
            # 设置图表的大小
            sns.set(rc={'figure.figsize':(11,12)})
            # 显示图表
            plt.savefig('income_marital_status.png')
            plt.show()
# 定义函数count_outliers，用于计算数据中指定列的异常值数量
# 参数data为数据，col为指定列
def count_outliers(data, col):
    # 计算指定列的四分位数
    q1 = data[col].quantile(0.25, interpolation='nearest')
    q2 = data[col].quantile(0.5, interpolation='nearest')
    q3 = data[col].quantile(0.75, interpolation='nearest')
    q4 = data[col].quantile(1, interpolation='nearest')
    # 计算四分位数之间的差值
    IQR = q3 - q1
    # 定义全局变量LLP和ULP
    global LLP
    global ULP
    # 计算下限和上限
    LLP = q1 - 1.5 * IQR
    ULP = q3 + 1.5 * IQR
    # 判断数据是否在上下限之间
    if data[col].min() > LLP and data[col].max() < ULP:
        print("No outliers in", i)
    else:
        print("There are outliers in", i)
        # 计算异常值的数量
        x = data[data[col] < LLP][col].size
        y = data[data[col] > ULP][col].size
        # 将异常值的数量添加到列表a中
        a.append(i)
        print('Count of outliers are:', x + y)


global a
a = []
for i in y.columns:
    count_outliers(df, i)


# 计算每个年龄段的统计信息
df1 = df.groupby('Age').agg({ 'Education' : 'count', 'Marital_Status' : 'count', 'Income':'mean', 'Kidhome' : 'count',
       'Teenhome' : 'count',  'Recency':'mean',
        'NumDealsPurchases' : 'mean', 'NumWebPurchases' : 'mean',
       'NumCatalogPurchases' : 'mean', 'NumStorePurchases' : 'mean', 'NumWebVisitsMonth' : 'mean',
        'Complain' : 'sum', 'Response' : 'sum', 'Spent' : 'mean'})
print(df1)

# 计算每个教育水平的统计信息
df2 = df.groupby('Education').agg({ 'Age' : 'mean', 'Education' : 'count', 'Marital_Status' : 'sum', 'Income':'mean', 'Kidhome' : 'count',
       'Teenhome' : 'count',  'Recency':'mean',
        'NumDealsPurchases' : 'mean', 'NumWebPurchases' : 'mean',
       'NumCatalogPurchases' : 'mean', 'NumStorePurchases' : 'mean', 'NumWebVisitsMonth' : 'mean',
        'Complain' : 'sum', 'Response' : 'sum', 'Spent' : 'mean'})
print(df2)

# 创建一个函数，用于绘制饼图
fig1=px.bar(data_frame=df2.drop(['Income','Marital_Status'],axis = 1), barmode='group',
       title = "<b>Education wise Analyzing</b>",template="plotly_dark")
fig1.save("Education_wise_Analyzing.html")
fig1.show()

df3 = df.groupby('Marital_Status').agg({ 'Age' : 'mean', 'Education' : 'count', 'Marital_Status' : 'sum', 'Income':'mean', 'Kidhome' : 'count',
       'Teenhome' : 'count',  'Recency':'mean',
        'NumDealsPurchases' : 'mean', 'NumWebPurchases' : 'mean',
       'NumCatalogPurchases' : 'mean', 'NumStorePurchases' : 'mean', 'NumWebVisitsMonth' : 'mean',
        'Complain' : 'sum', 'Response' : 'sum', 'Spent' : 'mean'})
print(df3)